#include "student.hxx"
#include "student-odb.hxx"
#include <string>
#include <memory>  // std::auto_ptr
#include <cstdlib> // std::exit
#include <iostream>
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include <gflags/gflags.h>

DEFINE_string(host, "127.0.0.1", "这是mysql服务器地址");
DEFINE_int32(port, 0, "这是mqsql服务端端口");
DEFINE_string(db, "TestDB", "这是数据库默认名称");
DEFINE_string(user, "root", "这是mysql登录用户");
DEFINE_string(pwd, "299274142", "这是mysql登录密码");
DEFINE_string(cset, "utf8", "这是mysql客户端字符集");
DEFINE_int32(max_pool, 3, "这是mqsql连接池最大链接数量");

void insert_classes(odb::mysql::database &db)
{
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        Classes c1("一年级一班");
        Classes c2("一年级二班");
        db.persist(c1);
        db.persist(c2);
        //提交事务
        trans.commit();
    }catch(std::exception &e){
        std::cout << "插入数据 失败" << e.what() << std::endl;   
    }
}

void insert_student(odb::mysql::database &db)
{
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        Student s1(1, "LiMing", 18, 1);
        Student s2(2, "LiMing2", 181, 1);
        Student s3(3, "LiMing3", 12, 2);
        Student s4(4, "LiMing4", 48, 12);
        db.persist(s1);
        db.persist(s2);
        db.persist(s3);
        db.persist(s4);
        //提交事务
        trans.commit();
    }catch(std::exception &e){
        std::cout << "插入数据 失败" << e.what() << std::endl;   
    }
}

void update_student(odb::mysql::database &db, Student &stu)
{
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        db.update(stu);
        //提交事务
        trans.commit();
    }catch(std::exception &e){
        std::cout << "更新数据 失败" << e.what() << std::endl;   
    }
}

Student select_student(odb::mysql::database &db)
{
    Student res;
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<Student> result;
        result r(db.query<Student>(query::name == "LiMing"));
        if(r.size() != 1)
        {
            std::cout << "数据量不对！" << std::endl;
            return Student(); 
        }
        res = *r.begin();

        //提交事务
        trans.commit();

    }catch(std::exception &e){
        std::cout << "查询数据 失败" << e.what() << std::endl;   
    }
    return res;
}

void remove_student(odb::mysql::database &db)
{
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        //db.erase_query<Student>(query::name == "after update");
        db.erase_query<Student>(query::classes_id == 2);
        //提交事务
        trans.commit();
    }catch(std::exception &e){
        std::cout << "删除数据 失败" << e.what() << std::endl;   
    }
}

void classes_student(odb::mysql::database &db)
{
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<struct classes_student> query;
        typedef odb::result<struct classes_student> result;
        result r(db.query<struct classes_student>(query::classes::name == "一年级一班"));

        for(auto &it : r)
        {
            std::cout << it.id<< std::endl;
            std::cout << it.sn<< std::endl;
            std::cout << it.name<< std::endl;
            if (it.age) std::cout << *it.age<< std::endl;
            std::cout << it.classes_name<< std::endl;
        }

        //提交事务
        trans.commit();

    }catch(std::exception &e){
        std::cout << "查询数据 失败" << e.what() << std::endl;   
    }
}

void all_student(odb::mysql::database &db)
{
    try
    {
        //开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<struct Student> query;
        typedef odb::result<struct all_name> result;
        result r(db.query<struct all_name>(query::id == 1));

        for(auto &it : r)
        {
            std::cout << it.name<< std::endl;
        }

        //提交事务
        trans.commit();

    }catch(std::exception &e){
        std::cout << "查询所有学生姓名 失败" << e.what() << std::endl;   
    }
}


int main(int argc, char *argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    // 构造连接池对象
    std::unique_ptr<odb::mysql::connection_pool_factory> cpf(new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));
    // 构造数据库操作对象
    odb::mysql::database db(FLAGS_user, FLAGS_pwd, FLAGS_db, FLAGS_host, FLAGS_port, "",  FLAGS_cset, 0, std::move(cpf));

    //数据操作
    //insert_classes(db);
    //insert_student(db);
    //auto stu = select_student(db);

    // auto stu = select_student(db);
    // std::cout << stu.sn()<< std::endl;
    // std::cout << stu.name()<< std::endl;
    // if (stu.age()) std::cout << *stu.age()<< std::endl;
    // std::cout << stu.classes_id()<< std::endl;
    //res.name("after update");

    //update_student(db, stu);
    //remove_student(db);
    //classes_student(db);
    all_student(db);
    // 提交事务
    return 0;
}